package com.csair.seam.infrastructure.poi.factory;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.StringUtils;

import com.csair.seam.infrastructure.poi.annotation.ExportField;
import com.csair.seam.infrastructure.poi.annotation.ImportField;
import com.csair.seam.infrastructure.poi.config.ExcelExportConfig;
import com.csair.seam.infrastructure.poi.entity.ExportFieldEntity;
import com.csair.seam.infrastructure.poi.entity.ImportFieldEntity;
import com.csair.seam.infrastructure.poi.exception.ExcelException;

public class ExcelMappingFactory {
	private static final Map<String, Map<String, ImportFieldEntity>> IMPORT_FIELD_HOLDER = new ConcurrentHashMap<>();
	private static final Map<String, Map<String, ExportFieldEntity>> EXPORT_FIELD_HOLDER = new ConcurrentHashMap<>();
	
	private ExcelMappingFactory() {
	}
	
	public static Map<String, ImportFieldEntity> loadImportFieldClass(Class<?> clazz) {
		if(IMPORT_FIELD_HOLDER.containsKey(clazz.getName())) {
			return IMPORT_FIELD_HOLDER.get(clazz.getName());
		}
		Field[] fields = clazz.getDeclaredFields();
		Map<String, ImportFieldEntity> map = new LinkedHashMap<>(fields.length);
		for (Field field : fields) {
			ImportField importField = field.getAnnotation(ImportField.class);
			if (null != importField) {
				if(map.containsKey(importField.name())){
					throw new ExcelException("[%s]类@ImportField注解【name=%s】属性配置重复!", clazz.getName(),importField.name());
				}
				field.setAccessible(true);
				ImportFieldEntity entity = new ImportFieldEntity();
				entity.setFieldName(field.getName());
				entity.setSimpleJavaType(field.getType().getSimpleName());
				entity.setImportField(importField);
				map.put(importField.name(), entity);
			}
		}
		if(map.isEmpty()) {
			throw new ExcelException("[{}]类未找到标注@ImportField注解的属性!", clazz.getName());
		}
		IMPORT_FIELD_HOLDER.put(clazz.getName(), map);
		return map;
	}
	
	public static Map<String, ExportFieldEntity> loadExportFieldClass(Class<?> clazz, ExcelExportConfig config) {
		
		String exportClass = StringUtils.isNotBlank(config.getExportClass()) ? config.getExportClass() : clazz.getName();
		if (EXPORT_FIELD_HOLDER.containsKey(exportClass)) {
			return EXPORT_FIELD_HOLDER.get(exportClass);
		}
		// 过滤属性
		List<String> ignores = new ArrayList<>();
		if (config.getIgnoreFields() != null) {
			ignores = Arrays.asList(config.getIgnoreFields());
		}
		
		Field[] fields = clazz.getDeclaredFields();
		Map<String, ExportFieldEntity> map = new LinkedHashMap<>(fields.length);
		for (Field field : fields) {
			ExportField exportField = field.getAnnotation(ExportField.class);
			// 当前字段不包含过滤字段
			if (null != exportField && !ignores.contains(field.getName())) {
				field.setAccessible(true);
				ExportFieldEntity entity = new ExportFieldEntity();
				entity.setFieldName(field.getName());
				entity.setSimpleJavaType(field.getType().getSimpleName());
				entity.setExportField(exportField);
				map.put(field.getName(), entity);
			}
		}
		if(map.isEmpty()) {
			throw new ExcelException("[{}]类未找到标注@ExportField注解的属性!", clazz.getName());
		}
		EXPORT_FIELD_HOLDER.put(exportClass, map);
		return map;
	}
	
	@Deprecated
	public static Map<String, ExportFieldEntity> loadExportFieldClass(Class<?> clazz) {
		if(EXPORT_FIELD_HOLDER.containsKey(clazz.getName())) {
			return EXPORT_FIELD_HOLDER.get(clazz.getName());
		}
		Field[] fields = clazz.getDeclaredFields();
		Map<String, ExportFieldEntity> map = new LinkedHashMap<>(fields.length);
		for (Field field : fields) {
			ExportField exportField = field.getAnnotation(ExportField.class);
			if (null != exportField) {
				field.setAccessible(true);
				ExportFieldEntity entity = new ExportFieldEntity();
				entity.setFieldName(field.getName());
				entity.setSimpleJavaType(field.getType().getSimpleName());
				entity.setExportField(exportField);
				map.put(field.getName(), entity);
			}
		}
		if(map.isEmpty()) {
			throw new ExcelException("[{}]类未找到标注@ExportField注解的属性!", clazz.getName());
		}
		EXPORT_FIELD_HOLDER.put(clazz.getName(), map);
		return map;
	}
}
